<?php
/**
 * Created by PhpStorm.
 * User: clkj1
 * Date: 2018/7/10
 * Time: 13:59
 */

require_once './phpqrcode/qrlib.php';
require_once './core/sql.php';

class makePoster
{

    function __construct()
    {
        $this->makeDir('./u-img/outs');
        $this::$underline_start_point = array();
        $this::$underline_end_point = array();
    }

    /**
     * 制作二维码功能
     * @param int $uid
     * @param string $contentString 二维码内容
     * @param int $size 二维码纠错等级：0最低，1低，2中等，3高
     * @param int $newWidth 新的二维码宽度
     * @param int $newHeight 新的二维码高度
     * @param string $logo logo的图片链接
     * @return string 输出保存的制作完图片地址
     */
    public function makeQRCode($uid, $contentString = '', $size = 3, $newWidth = 201, $newHeight = 201, $logo = '')
    {
        //创建随机数，用来给二维码命名
        $outName = $this->fileReName();
        $outName .= '.png';
        //设定输出二维码的相对路径
        $relative_path = "./u-img/outs/$outName";
        //实例化一个QRCode类
        $phpQRCode = new QRcode();
        //制作出二维码
        $phpQRCode::png($contentString, $relative_path, $size, 3, 1);
        //二维码图片转资源
        $relative_Code = $this->createImageFromFile($relative_path);
        //将制作出的二维码图片资源宽度高度改成201，201，图片地址为刚制作出的二维码，输出图片资源
        $changeCode = $this->changeImagePixel($newWidth, $newHeight, $relative_Code, 201, 201);
        //如果要添加logo的
        if ($logo != '' && $logo != null) {
            //图片文件转成资源
            $logo_im = $this->createImageFromFile($logo);
            //将logo图片宽高改完
            $changeLogo = $this->changeImagePixel(45, 45, $logo_im, 45, 45);
            //将logo放到二维码上
            imagecopy($changeCode, $changeLogo, (201 / 2 - 45 / 2), (201 / 2 - 45 / 2), 0, 0, 45, 45);
        }
        $sql = new SqlS();
        $sql->addTimeOutImages($uid, $relative_path);
        imagepng($changeCode, $relative_path);
        imagedestroy($changeCode);
        //输出二维码保存地址
        return $relative_path;
    }

    /**
     * 随机数命名
     * @param int $size 复杂程度
     * @param int $length 长度
     * @return string
     */
    public function fileReName($size = 6, $length = 10)
    {
        //创建随机数，用来给二维码命名
        $numbers = range(0, 9);
        $letters_s = range('a', 'z');
        $letters_b = range('A', 'Z');
        switch ($size) {
            case 0:
                $changeStr = join('', $numbers);
                break;
            case 1:
                $changeStr = join('', $letters_s);
                break;
            case 2:
                $changeStr = join('', $letters_b);
                break;
            case 3:
                $changeStr = join("", array_merge($numbers, $letters_s));
                break;
            case 4:
                $changeStr = join("", array_merge($numbers, $letters_b));
                break;
            case 5:
                $changeStr = join("", array_merge($letters_s, $letters_b));
                break;
            case 6:
                $changeStr = join('', array_merge($numbers, $letters_s, $letters_b));
                break;
            default :
                $changeStr = join('', array_merge($numbers, $letters_s, $letters_b));
        }
        $outName = str_shuffle($changeStr){0};
        for ($i = 0; $i < $length; $i++) {
            $outName .= str_shuffle($changeStr){0};
        }
        return $outName;
    }

    /**
     * 设定图片宽高改变图片大小的缩放功能
     * @param int $width 改变宽度为
     * @param int $height 改变高度为
     * @param resource $image 图片资源
     * @param int $high_x 尽可能大的x
     * @param int $high_y 尽可能大的y
     * @return resource 改变后的图像资源
     */
    public function changeImagePixel($width = 0, $height = 0, $image, $high_x = 1080, $high_y = 1829)
    {
        //获取图片宽高
        list($image_width, $image_height) = array(imagesx($image), imagesy($image));
        //创图片背景，大小为要设定的大小
        $image_bg = imagecreatetruecolor($high_x, $high_y);
        //透明色
        $transparent = imagecolorallocatealpha($image_bg, 0, 0, 0, 127);
        //上透明色
        imagefill($image_bg, 0, 0, $transparent);
        //缩放
        imagecopyresampled($image_bg, $image, 0, 0, 0, 0, $width, $height, $image_width, $image_height);
        //输出图像资源
        return $image_bg;
    }

    /**
     * 旋转照片：
     * @param resource $image
     * @param int $rotate
     * @return resource
     */
    public function rotateImage($image, $rotate = 0)
    {
        $transparent = imagecolorallocatealpha($image, 0, 0, 0, 127);
        $rotated = imagerotate($image, $rotate, $transparent, 1);
        return $rotated;
    }

    /**
     * 裁剪图片功能
     * @param resource $image 需要裁剪的图片
     * @param array $new_image_point 裁剪左上角坐标
     * @param int $new_image_w 裁剪后宽度
     * @param int $new_image_h 裁剪后高度
     * @return resource 裁剪后的图像资源
     */
    public function cutImage($image, $new_image_point = array(0, 0), $new_image_w = 0, $new_image_h = 0)
    {
        list($new_image_x, $new_image_y) = $new_image_point;
        //创建背景为裁剪后大小
        $image_bg = imagecreatetruecolor($new_image_w, $new_image_h);
        //透明色
        $transparent = imagecolorallocatealpha($image_bg, 0, 0, 0, 127);
        //填充透明色
        imagefill($image_bg, 0, 0, $transparent);
        //裁剪
        imagecopyresampled($image_bg, $image, 0, 0, $new_image_x, $new_image_y, $new_image_w, $new_image_h, $new_image_w, $new_image_h);
        return $image_bg;
    }

    /**
     * 从文件转成图像资源功能，输出图像资源
     * @param string $image_file
     * @return resource
     */
    public function createImageFromFile($image_file = '')
    {
        list($image_width, $image_height, $image_size) = getimagesize($image_file);
        $image_bg = imagecreatetruecolor($image_width, $image_height);
        $transparent = imagecolorallocatealpha($image_bg, 0, 0, 0, 127);
        imagefill($image_bg, 0, 0, $transparent);
        //图片转成图像资源
        switch ($image_size) {
            case 1:
                $image = imagecreatefromgif($image_file);
                imagecopyresampled($image_bg, $image, 0, 0, 0, 0, $image_width, $image_height, $image_width, $image_height);
                return $image_bg;
                break;
            case 2:
                $image = imagecreatefromjpeg($image_file);
                imagecopyresampled($image_bg, $image, 0, 0, 0, 0, $image_width, $image_height, $image_width, $image_height);
                return $image_bg;
                break;
            case 3:
                $image = imagecreatefrompng($image_file);
                imagecopyresampled($image_bg, $image, 0, 0, 0, 0, $image_width, $image_height, $image_width, $image_height);
                return $image_bg;
                break;
            default:
                // TODO ...
                //如果图片有问题则输出这个图片
                $image_bg_error = imagecreatetruecolor($image_width, $image_height);
                //白色背景
                $white = imagecolorallocate($image_bg_error, 255, 255, 255);
                //填充
                imagefill($image_bg_error, 0, 0, $white);
                //灰色字体
                $gray = imagecolorallocate($image_bg_error, 150, 150, 150);
                imagettftext($image_bg_error, 5, 0, 0, 0, $gray, __DIR__ . '/fonts/Deng.ttf', '错误图片！');
                return $image_bg_error;
        }
    }

    // 静态变量 用来存储蓄目前是第几个字 用于换行
    public static $now_text_num;
    public static $now_text_line;
    // replace(/\[灰\]/g, "<gray>").replace(/\[\/灰\]/g, "</gray>").
    // replace(/\[红\]/g, "<red>").replace(/\[\/红\]/g, "</red>").
    // replace(/\[粗\]/g, "<bold>").replace(/\[\/粗\]/g, "</bold>").
    // replace(/\[斜\]/g, "<italic>").replace(/\[\/斜\]/g, "</italic>").
    // replace(/\[下划线\]/g, "<underline>").replace(/\[\/下划线\]/g, "</underline>").
    // replace(/\[大\]/g, "<large>").replace(/\[\/大\]/g, "</large>")
    public function fixText($image, $text, $type = 0)
    {
        $text = trim($text);
        // 加入<br />还行符
        $text = nl2br($text);
        // 重置输出文字字数
        $this::$now_text_num = 0;
        $this::$now_text_line = 0;

        $all_count = $this->mb_str_count("$text");
        while (1 < $all_count) {
            // 初始化排序数组：
            $px_array = array();

            $nie_array = array(array('gray', 6), array('red', 5), array('bold', 6), array('italic', 8), array('line', 6), array('large', 7));
            for ($i = 0; $i < count($nie_array); $i++) {
                $result = $this->returnArrayX($text, $nie_array[$i][0], $nie_array[$i][1]);
                if ($result[0] == true) {
                    $px_array[] = $result[1];
                }
            }
            $result = $this->returnArrayX($text, 'br', 6, 1);
            if ($result[0] == true) {
                $px_array[] = $result[1];
            }

            $font_array = array(
                '等线常规' => __DIR__ . '/fonts/Deng.ttf',
                '等线粗体' => __DIR__ . '/fonts/Dengb.ttf',
                '等线细体' => __DIR__ . '/fonts/Dengl.ttf'
            );
            $color_type = 0;
            $angle = 0;
            $underline = false;
            switch ($type) {
                case 0:
                    $start_point = array(115, 585);
                    $size = 19;
                    $line_count = 30;
                    $line_height = 35;
                    $font_width = $size + 8;
                    break;
                case 1:
                    $start_point = array(218, 750);
                    $size = 30;
                    $line_count = 25;
                    $line_height = 80;
                    $font_width = $size + 10;
                    $font_array = array(
                        '等线常规' => __DIR__ . '/fonts/Dengb.ttf',
                        '等线粗体' => __DIR__ . '/fonts/Dengb.ttf',
                        '等线细体' => __DIR__ . '/fonts/Dengb.ttf'
                    );
                    break;
                case 2:
                    $start_point = array(180, 1520);
                    $size = 22;
                    $line_count = 20;
                    $line_height = 50;
                    $font_width = $size + 8;
                    break;
                default :
                    $start_point = array(115, 585);
                    $size = 19;
                    $line_count = 30;
                    $line_height = 30;
                    $font_width = $size + 10;
                    break;
            }

            // 冒泡排序：
            if ($px_array != array()) {
                $cnt = count($px_array);
                for ($i = 0; $i < $cnt - 1; $i++) {
                    for ($j = 0; $j < $cnt - $i - 1; $j++) {
                        if ($px_array[$j][0] > $px_array[$j + 1][0]) {
                            $temp = $px_array[$j];
                            $px_array[$j] = $px_array[$j + 1];
                            $px_array[$j + 1] = $temp;
                        }
                    }
                }

                if ($px_array[0][1] == 'br') {
                    list($first_set, $ku_name, $name_long) = $px_array[0];
                    $first_set -= 1;
                    if ($first_set > 0) {
                        // 普通 绘制第一串文字 前两个字
                        $text_out = mb_substr($text, 0, $first_set);
                        $this->writeText($image, $start_point, $font_array['等线常规'], $text_out, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);
                    }
                    // $text 变成后面不包括了框的文字
                    $text = mb_substr($text, $first_set + $name_long);
                    // (换行+1)
                    $this::$now_text_line += 1;
                    // 文字起点归零
                    $this::$now_text_num = 0;
                } else {
                    //  0 代表这个框出现的第1个位置
                    //  1 代表这个框的名称 e.g. red
                    //  2 其中的文字是什么
                    //  3 有几个字
                    //  4 框的名字长度是什么 e.g. red 是 5
                    list($first_set, $ku_name, $in_text, $in_text_num, $name_long) = $px_array[0];
                    // 第一个框
                    $px_array[0][1];
                    // 普通 绘制第一串文字 前两个字

                    if ($first_set > 0) {
                        $text_out = mb_substr($text, 0, $first_set);

                        $this->writeText($image, $start_point, $font_array['等线常规'], $text_out, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);
                    }

                    // $text 变成后面包括了框的文字
                    $text = mb_substr($text, $first_set);
                    // 绘制 $ku_name 的文字 从第 $ku_name 到n个字
                    $text_out = mb_substr($text, $name_long, $in_text_num);// ($in_text)

                    if ($ku_name == 'gray')
                        $color_type = 2;
                    if ($ku_name == 'red')
                        $color_type = 1;
                    if ($ku_name == 'bold')
                        $fonts = $font_array['等线粗体'];
                    else
                        $fonts = $font_array['等线常规'];
                    if ($ku_name == 'italic')
                        $angle = -8;
                    if ($ku_name == 'line')
                        $underline = true;
                    if ($ku_name == 'large')
                        $size = $size + 5;

                    // 里面再进行循环检测？最多嵌套两层
                    $text2 = $text_out;
                    $all_count2 = $this->mb_str_count("$text2");
                    while (1 < $all_count2) {
                        // 初始化排序数组：
                        $px_array2 = array();

                        $nie_array2 = array(array('gray', 6), array('red', 5), array('bold', 6), array('italic', 8), array('line', 6), array('large', 7));
                        for ($i = 0; $i < count($nie_array2); $i++) {
                            $result2 = $this->returnArrayX($text2, $nie_array2[$i][0], $nie_array2[$i][1]);
                            if ($result2[0] == true) {
                                $px_array2[] = $result2[1];
                            }
                        }
                        $result2 = $this->returnArrayX($text2, 'br', 6, 1);
                        if ($result2[0] == true) {
                            $px_array2[] = $result2[1];
                        }
                        // 冒泡排序：
                        if ($px_array2 != array()) {
                            $cnt2 = count($px_array2);
                            for ($i = 0; $i < $cnt2 - 1; $i++) {
                                for ($j = 0; $j < $cnt2 - $i - 1; $j++) {
                                    if ($px_array2[$j][0] > $px_array2[$j + 1][0]) {
                                        $temp2 = $px_array2[$j];
                                        $px_array2[$j] = $px_array2[$j + 1];
                                        $px_array2[$j + 1] = $temp2;
                                    }
                                }
                            }
                            if ($px_array2[0][1] == 'br') {
                                list($first_set2, $ku_name2, $name_long2) = $px_array2[0];
                                $first_set2 -= 1;
                                if ($first_set2 > 0) {
                                    // 普通 绘制第一串文字 前两个字
                                    $text_out2 = mb_substr($text2, 0, $first_set2);
                                    $this->writeText($image, $start_point, $fonts, $text_out2, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);
                                }
                                // $text 变成后面不包括了框的文字
                                $text2 = mb_substr($text2, $first_set2 + $name_long2);

                                // (换行+1)
                                $this::$now_text_line += 1;
                                // 文字起点归零
                                $this::$now_text_num = 0;
                            } else {
                                //  0 代表这个框出现的第1个位置
                                //  1 代表这个框的名称 e.g. red
                                //  2 其中的文字是什么
                                //  3 有几个字
                                //  4 框的名字长度是什么 e.g. red 是 5
                                list($first_set2, $ku_name2, $in_text2, $in_text_num2, $name_long2) = $px_array2[0];
                                // 第一个框
                                $px_array2[0][1];
                                // 普通 绘制第一串文字 前两个字

                                if ($first_set2 > 0) {
                                    $text_out2 = mb_substr($text2, 0, $first_set2);

                                    $this->writeText($image, $start_point, $fonts, $text_out2, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);
                                }

                                // $text 变成后面包括了框的文字
                                $text2 = mb_substr($text2, $first_set2);
                                // 绘制 $ku_name 的文字 从第 $ku_name 到n个字
                                $text_out2 = mb_substr($text2, $name_long2, $in_text_num2);// ($in_text)


                                if ($ku_name2 == 'gray')
                                    $color_type = 2;
                                if ($ku_name2 == 'red')
                                    $color_type = 1;
                                if ($ku_name2 == 'bold')
                                    $fonts = $font_array['等线粗体'];
                                else
                                    $fonts = $font_array['等线常规'];
                                if ($ku_name2 == 'italic')
                                    $angle = -8;
                                if ($ku_name2 == 'line')
                                    $underline = true;
                                if ($ku_name2 == 'large')
                                    $size = $size + 5;
                                $this->writeText($image, $start_point, $fonts, $text_out2, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);
                                // $text 变成后面的文字
                                $text2 = mb_substr($text2, $name_long2 * 2 + 1 + $in_text_num2);
                            }
                        } else {
                            // $text 变成后面的文字
                            $text2 = mb_substr($text2, 0);
                            // 普通 绘制 最后 的文字 normal
                            $text_out2 = mb_substr($text2, 0);

                            $this->writeText($image, $start_point, $fonts, $text_out2, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);

                            // $text 变成空
                            $text2 = '';
                        }
// 文字计数
                        $all_count2 = $this->mb_str_count("$text2");
                    }

                    //
//                    $this->writeText($image, $start_point, $fonts, $text2, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);
//                    $this->writeText($image, $start_point, $fonts, $text_out, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);

                    // $text 变成后面的文字
                    $text = mb_substr($text, $name_long * 2 + 1 + $in_text_num);
                }
            } else {
                // $text 变成后面的文字
                $text = mb_substr($text, 0);
                // 普通 绘制 最后 的文字 normal
                $text_out = mb_substr($text, 0);

                $this->writeText($image, $start_point, $font_array['等线常规'], $text_out, $size, $color_type, $line_count, $line_height, $angle, $font_width, $underline);

                // $text 变成空
                $text = '';
            }
// 文字计数
            $all_count = $this->mb_str_count("$text");
        }
        return $image;
    }

    /**
     * 全部文字
     * @param string $text
     * @param string $name 文字框名 如 red
     * @param int $long 文字框前部总长 如 red 5 (<red>)
     * @param int $type
     * @return array 0 是否有出现 10 第一个位置（用来衡量是否是第一个） 11 名字 就是输入的$name 12 这个文字框中的字是什么。 13 这个文字框中也就是12的字有几个 14 这个文字框的长度就是输入的$long
     */
    public function returnArrayX($text, $name, $long, $type = 0)
    {
        if ($type == 0) {
            // 所有 这个 框的文字array
            preg_match_all("|<[$name]+>(.*)</[$name]+>|U",
                "$text",
                $textOut,
                PREG_PATTERN_ORDER);

            if (isset($textOut[1][0])) {
//  这个 文字框 第一个中的文字字数
                $text_count = $this->mb_str_count($textOut[1][0]);
// 这个 文字框中的字是什么
                $text_first = $textOut[1][0];
            } else {
                $text_count = 0;
                $text_first = null;
            }
            if ($text_first != null) {
// 这个 第一个的出现的 位置
                $t_text = mb_strpos($text, "<$name>" . $text_first . "</$name>");
                return array(true, array($t_text, $name, $text_first, $text_count, $long));
            } else {
                return array(false);
            }
        } else if ($type == 1) {
            // 所有 <br /> 框的文字array
// 这个 第一个的出现的 位置
            $text_first = mb_strpos($text, 'br />');
            if ($text_first > 0)
                return array(true, array($text_first, $name, 6));
            else
                return array(false);
        }
    }

    private static $underline_start_point;
    private static $underline_end_point;


    // 一个字一个字绘制，先拆分字，然后
    // 图像，起点，字体，文字，大小，一行多少字，行距, 文字对齐类型(right, center(, left))，第几行文字
    //* @param string $underline 下划线 false 无 start 开始 end 结束
    public function writeText($image, $start_point = array(115, 585), $font = '', $text = '内容介绍，', $size = 19, $color_type = 0, $line_count = 30, $line_height = 0, $angle = 0, $font_width, $underline)
    {
        $black = imagecolorallocate($image, 0, 0, 0);
        $deep_red = imagecolorallocate($image, 213, 23, 23);
        $gray = imagecolorallocate($image, 128, 128, 128);
        $start_x = $start_point[0];
        $start_y = $start_point[1];
        $content_array = $this->mb_str_split($text);
        $count_content = count($content_array);

        switch ($color_type) {
            case 0:
                $color = $black;
                break;
            case 1:
                $color = $deep_red;
                break;
            case 2:
                $color = $gray;
                break;
            default :
                $color = $black;
        }

        for ($i = 0; $i < $count_content; $i++) {

            if ($this::$now_text_num > $line_count) {
                $this::$now_text_num = 0;
                $this::$now_text_line += 1;
            }

            $text_position_x = $start_x + $font_width * $this::$now_text_num;
            $text_position_y = $start_y + $this::$now_text_line * $line_height;
            if ($underline == true) {
                imageline($image, $text_position_x, $text_position_y + 10, $text_position_x + $font_width, $text_position_y + 10, $color);
            }
            // 绘制单个字
            imagettftext($image, $size, $angle, $text_position_x, $text_position_y, $color, $font, $content_array[$i]);

            $this::$now_text_num += $this->qj($content_array[$i]);


        }

        return $image;
    }

    // 判断是否为中文字符
    public function qj($str)
    {
        if (preg_match_all("/[\x7f-\xff]/", "$str")) {
            return 1;
        } elseif (preg_match_all('/[\`\~\!\@\#\$\%\^\&\*\(\)\_\+\-\=\[\]\{\}\\\|\;\'\'\:\\"\\"\,\.\/\<\>\?]/', "$str")) {
            return 0.4;
        } elseif ($str == ' ') {
            return 0.5;
        } else {
            return 0.6;
        }
    }

    // 裁剪code图片
    // 图片的宽高im_w/h|框选的坐标cut_xy[matrix(1, 0, 0, 1, -41.1, -41.1)]|框选的宽高cut_w/h|上传图片链接
    /**
     * @param $im_wi
     * @param $im_he
     * @param $cut_xy
     * @param $cut_wi
     * @param $cut_he
     * @param $file
     * @return string
     */
    public function cutCode($im_wi, $im_he, $cut_xy, $cut_wi, $cut_he, $file)
    {
        // 文字转数字：
        $im_wi = substr($im_wi, 0, strlen($im_wi) - 2);
        $im_he = substr($im_he, 0, strlen($im_he) - 2);
        $cut_wi = substr($cut_wi, 0, strlen($cut_wi) - 2);
        $cut_he = substr($cut_he, 0, strlen($cut_he) - 2);
        // 将cut_xy坐标进行解析：
        // 1. 裁剪为 "1, 0, 0, 1, -41.1, -41.1)"
        $cut_xy = substr($cut_xy, 7);
        // 2. 去掉最后面的 ")"
        $cut_xy = substr($cut_xy, 0, strlen($cut_xy) - 1);
        // 3. 最后得到的是 "1, 0, 0, 1, -41.1, -41.1"
        $cut_xys = explode(',', $cut_xy);
        // 4. 最后得到的x 就是[4],y [5]
        // 创建图片
        $image = $this->createImageFromFile($file);
        // 变更大小
        $image = $this->changeImagePixel($im_wi, $im_he, $image);
        // 创建裁剪大小的图片
        $cut_image = $this->cutImage($image, array(abs($cut_xys[4]), abs($cut_xys[5])), $cut_wi, $cut_he);
        $cut_image = $this->changeImagePixel(201, 201, $cut_image, 201, 201);
        $reName = $this->fileReName();
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        imagesavealpha($cut_image, true);// 保存时保留透明度
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // 输出图片裁剪后的图片
        imagepng($cut_image, "./outs/$reName.png");
        imagedestroy($cut_image);
        // 输出图片地址
        return "./outs/$reName.png";
    }

    /**
     * 将字符串分割为数组
     *
     * @param  string $str 字符串
     *
     * @return array       分割得到的数组
     */
    public function mb_str_split($str)
    {
        return preg_split('/(?<!^)(?!$)/u', $str);
    }

    // 字符串长度
    public function mb_str_count($str)
    {
        return count($this->mb_str_split($str));
    }

    // 创建文件夹
    public function makeDir($dir)
    {
        // 如果文件夹不存在，将以递归方式创建该文件夹
        is_dir($dir) OR mkdir($dir, 0777, true);
    }

    function __destruct()
    {
        // TODO: Implement __destruct() method.
    }
}